package com.dbflow5.adapter.queriable;

import com.dbflow5.adapter.RetrievalAdapter;
import com.dbflow5.config.FlowManager;
import com.dbflow5.database.DatabaseWrapper;
import com.dbflow5.database.FlowCursor;

/**
 * Description: Represents how models load from DB. It will query a [DatabaseWrapper]
 * and query for a [FlowCursor]. Then the cursor is used to convert itself into an object.
 */
public abstract class ModelLoader<TModel, TReturn>{
    private Class<TModel> modelClass;

    protected RetrievalAdapter<TModel> instanceAdapter;

    public ModelLoader(Class<TModel> modelClass) {
        this.modelClass = modelClass;
    }

    public RetrievalAdapter<TModel> getInstanceAdapter() {
        if(instanceAdapter == null){
            instanceAdapter = FlowManager.getRetrievalAdapter(modelClass);
        }
        return instanceAdapter;
    }

    /** Loads the data from a query and returns it as a [TReturn].
     *
     * @param databaseWrapper A custom database wrapper object to use.
     * @param query           The query to call.
     * @return The data loaded from the database.
     */
    public TReturn load(DatabaseWrapper databaseWrapper, String query){
         return load(databaseWrapper.rawQuery(query, null), databaseWrapper);
    }

    public TReturn load(FlowCursor cursor, DatabaseWrapper databaseWrapper){
        return (TReturn) convertToData(cursor, databaseWrapper);
    }

    /**
     * Specify how to convert the [FlowCursor] data into a [TReturn]. Can be null.
     *
     * @param cursor The cursor resulting from a query passed into [.load]
     * @param databaseWrapper databaseWrapper
     * @return A new (or reused) instance that represents the [FlowCursor].
     */
    public abstract TReturn convertToData(FlowCursor cursor, DatabaseWrapper databaseWrapper);
}
